//
//  ViewModelIndexPosition.cpp
//  Chart
//
//  Created by CaoJun on 15/1/14.
//
//

#include "ViewModelIndexPosition.h"
#include "YTXChartTools.h"
#import "KLineDataList.h"
using namespace std;
using namespace ytx;

ViewModelIndexPosition::ViewModelIndexPosition()
: startDataIndex(0)
, endDataIndex(0)
, totalDataCount(0)
, minShowViewCount(0)
, maxShowViewCount(0)
, showViewCount(0)
, data(NULL)
{
    changeStep = 0;
}

ViewModelIndexPosition::ViewModelIndexPosition(int minShowViewCount, int maxShowViewCount)
: minShowViewCount(minShowViewCount)
, maxShowViewCount(maxShowViewCount)
, startDataIndex(0)
, endDataIndex(0)
, totalDataCount(0)
, showViewCount(0)
, data(NULL)
{
    changeStep = 0;
}

//data, rect 必须之前设过
void ViewModelIndexPosition::initViewIndexByDataIndexAndRect(int showViewCount)
{
    if(data != NULL){
        initViewIndexByDataIndexAndRect(data, showViewCount, minShowViewCount, maxShowViewCount);
    }
}

void ViewModelIndexPosition::initViewIndexByDataIndexAndRect(Quotation * data)
{
    initViewIndexByDataIndexAndRect(data, rect, data->getDrawingCount(), 0, data->getDrawingCount());
}

void ViewModelIndexPosition::initViewIndexByDataIndexAndRect(Quotation * data, int showViewCount)
{
    initViewIndexByDataIndexAndRect(data, rect, showViewCount, 0, data->getDataLength());
}

void ViewModelIndexPosition::initViewIndexByDataIndexAndRect(Quotation * data, int showViewCount, int minShowViewCount, int maxShowViewCount)
{
    initViewIndexByDataIndexAndRect(data, rect, showViewCount, minShowViewCount, maxShowViewCount);
}

void ViewModelIndexPosition::initViewIndexByDataIndexAndRect(Quotation * data, Rectangle rect, int showViewCount, int minShowViewCount, int maxShowViewCount)
{
    if(data == NULL){
        return;
    }
    
    this->data = data;
    
    this->rect = rect;
    
    this->minShowViewCount = minShowViewCount;
    
    this->maxShowViewCount = maxShowViewCount;

    this->showViewCount = showViewCount;

    this->totalDataCount = data->getDataLength();
    this->endDataIndex = totalDataCount;
    this->startDataIndex = fixStartDataIndex(this->endDataIndex -  showViewCount);
    this->changeStep = 0;
    
    setPara(data);
}

void ViewModelIndexPosition::resetPara()
{
    setPara(data);
}

void ViewModelIndexPosition::setPara(Quotation * data)
{
    if (data == NULL) {
        return;
    }
    this->data = data;
    
//    totalDataCount = data->getDataLength();
    
    data->setDrawingCount(showViewCount);
    
    rect.setZoomX(showViewCount);
    
    rect.resetRowAndColumn(data->row, data->column);
    
    pair<double, double> minMax = data->getAdjustedDataMinMax( getStartDataIndex(), getEndDataIndex(), rect);
    rect.setRectanglePara(minMax.second, minMax.first);
}

void ViewModelIndexPosition::setRectangle(Rectangle rect)
{
    this->rect = rect;
}

Rectangle& ViewModelIndexPosition::getRectangle()
{
    return rect;
}

int ViewModelIndexPosition::fixShowViewCount(int showViewCount)
{
    return Tools::between(minShowViewCount, maxShowViewCount, showViewCount);
}

int ViewModelIndexPosition::fixStartDataIndex(int startDataIndex)
{
    return Tools::between(0, totalDataCount, startDataIndex);
}

int ViewModelIndexPosition::fixStartDataIndexDrag(int startDataIndex)
{
    float halfWidth = rect.getRectWidth() * 0.5;
    
    float beginX = rect.getBeginX();
    
    int diff = MAX( 0, rect.getDiffBetweenTwoPx(beginX, beginX+halfWidth) );
    
    return Tools::between(0, totalDataCount - diff, startDataIndex);
}


int ViewModelIndexPosition::fixEndDataIndex(int endDataIndex)
{
    return Tools::between(MIN(showViewCount, totalDataCount), MAX(showViewCount, totalDataCount), endDataIndex);
}

void ViewModelIndexPosition::setShowViewCount(int showViewCount)
{
    showViewCount = fixShowViewCount(showViewCount);

    int diff = this->showViewCount - showViewCount;

    startDataIndex = fixStartDataIndex( startDataIndex + diff);

    this->showViewCount = showViewCount;
    
    setPara(data);
}

bool ViewModelIndexPosition::isTheLastDataIndex()
{
    return hadInited() && endDataIndex == totalDataCount;
}

//如果数据来新的了 想后移动
bool ViewModelIndexPosition::concatCount(Quotation * data){
    int diff = data->getDataLength() - totalDataCount;
    
    if (!hadInited() || (isTheLastDataIndex() && diff > 0 && startDataIndex >= (totalDataCount - showViewCount) )) {
        
        totalDataCount = data->getDataLength();
        
        startDataIndex = fixStartDataIndex( totalDataCount - showViewCount );
        endDataIndex = totalDataCount;
        setPara(data);
        return true;
    }
    else if (diff > 0){
        //向前移动了等于说
        totalDataCount = data->getDataLength();
        startDataIndex += diff;
        endDataIndex += diff;
        setPara(data);
    }
    return false;
}

void ViewModelIndexPosition::setTotalDataCount(int totalDataCount)
{
    int diff = totalDataCount - this->totalDataCount;

    if (isTheLastDataIndex()) {
        //diff>0增加了
        startDataIndex += diff;
        endDataIndex += diff;
    }

    this->totalDataCount = totalDataCount;
    
    setPara(data);

}

//负数为缩小
void ViewModelIndexPosition::zoom(int step){
    if (totalDataCount <= showViewCount) {
        //这种情况不让缩放
        return;
    }
    
    showViewCount = fixShowViewCount(showViewCount + step);

    startDataIndex = fixStartDataIndex(endDataIndex - showViewCount);
    
    setPara(data);

}

void ViewModelIndexPosition::zoomByScaleBegin(float scale)
{
    originShowViewCount = showViewCount;
    originScale = scale;
}

void ViewModelIndexPosition::zoomByScale(float scale)
{
    if (totalDataCount <= showViewCount) {
        //这种情况不让缩放
        return;
    }
    
    float percent = originScale / scale;
    
    showViewCount = fixShowViewCount( int(originShowViewCount * percent) );
    
    startDataIndex = fixStartDataIndex(endDataIndex - showViewCount);
    
    setPara(data);
    
}


//负数为缩小
void ViewModelIndexPosition::drag(int step){
    if (this->hjjtGJPermission() && changeStep == 0 && step != 0) {
        startDataIndex += 14;
        changeStep = step;
    }
    
    startDataIndex = fixStartDataIndexDrag( startDataIndex + step);
    endDataIndex = MIN(totalDataCount, startDataIndex + showViewCount);
    
    setPara(data);
}

int ViewModelIndexPosition::getDataIndexByPX(float x)
{
    return Tools::between(0, totalDataCount-1, startDataIndex + rect.getViewIndexByPX(x));
}

int ViewModelIndexPosition::getViewIndexByPX(float x)
{
    return fixStartDataIndex( getDataIndexByPX(x) - startDataIndex );
}

int ViewModelIndexPosition::getViewIndexByDataIndex(int index)
{
    return Tools::between(0, showViewCount ,index - startDataIndex);
}

int ViewModelIndexPosition::getViewPxByDataIndexWithoutModify(int index)
{
    return rect.getViewPxByViewIndexWithoutModify( index - startDataIndex );
}

float ViewModelIndexPosition::getViewPxByDataIndex(int index)
{
    return rect.getViewPxByViewIndex( getViewIndexByDataIndex(index) );
}

float ViewModelIndexPosition::getViewPxByViewIndex(int index)
{
    return rect.getViewPxByViewIndex( index );
}

int ViewModelIndexPosition::getStartDataIndex()
{
    if (this->hjjtGJPermission() && changeStep == 0) {
        return startDataIndex + 14;
    }
    return startDataIndex;
}

int ViewModelIndexPosition::getEndDataIndex()
{
    return endDataIndex;
}

int ViewModelIndexPosition::getEndDataIndexInRange()
{
    return endDataIndex - 1;
}

int ViewModelIndexPosition::getShowViewCount()
{
    return showViewCount;
}


bool ViewModelIndexPosition::hadInited()
{
    return totalDataCount > 0;
}


bool ViewModelIndexPosition::isRightEmpty(){
    return startDataIndex + showViewCount > totalDataCount;
}

Quotation * ViewModelIndexPosition::getData(){
    return data;
}

bool ViewModelIndexPosition::hjjtGJPermission()
{
    if (data != NULL && data->id.length() != 0) {
        KLineData *data0 = KLineDataList::getInstance()->get(data->id, LineType::L60m);
        IndexConfig indexConfig = data0->getIndexConfig(IndexType::HJJT);
        if (indexType == IndexType::HJJT){
            
            if(indexConfig.getIndexPermission() >= 2 ){
                return true;
            }
        }
    }
    return false;
}
